import { Particle, Robot, ConnectionLine, ExplosionFragmentParticle } from './types';
import {
  PARTICLE_SIZE_RANGE,
  PARTICLE_SPEED_FACTOR,
  BIG_BANG_THRESHOLD,
  MAX_PARTICLES,
  BIG_BANG_PARTICLE_COUNT,
  BIG_BANG_MAX_DISTANCE,
  ENERGY_CONSERVATION
} from './constants';

// 随机颜色生成
export const getRandomColor = (): string => {
  const colors = [
    'rgba(99, 102, 241, 0.8)',  // 紫色
    'rgba(79, 70, 229, 0.8)',   // 靛蓝色
    'rgba(67, 56, 202, 0.8)',   // 深紫色
    'rgba(109, 40, 217, 0.7)',  // 紫罗兰色
  ];
  return colors[Math.floor(Math.random() * colors.length)];
};

// 创建新粒子
export const createParticle = (
  canvas: HTMLCanvasElement,
  particlesRef: React.MutableRefObject<Particle[]>,
  x?: number,
  y?: number,
  size?: number,
  speedX?: number,
  speedY?: number,
  color?: string
): Particle | null => {
  // 如果已达到最大粒子数，不再创建新粒子
  if (particlesRef.current.length >= MAX_PARTICLES) {
    return null;
  }
  
  const particleX = x ?? Math.random() * canvas.width;
  const particleY = y ?? Math.random() * canvas.height;
  const particleSize = size ?? (PARTICLE_SIZE_RANGE.min + Math.random() * (PARTICLE_SIZE_RANGE.max - PARTICLE_SIZE_RANGE.min));
  const partSpeedX = speedX ?? (Math.random() - 0.5) * PARTICLE_SPEED_FACTOR;
  const partSpeedY = speedY ?? (Math.random() - 0.5) * PARTICLE_SPEED_FACTOR;
  const particleColor = color ?? getRandomColor();
  const maxLife = 300 + Math.random() * 200; // 粒子寿命

  const newParticle: Particle = {
    x: particleX,
    y: particleY,
    size: particleSize,
    speedX: partSpeedX,
    speedY: partSpeedY,
    color: particleColor,
    opacity: 0.1 + Math.random() * 0.5,
    life: 0,
    maxLife,
    id: Date.now() + Math.random(),
    mergeCount: 0,
    merging: false,
    mergeProgress: 0,
    exploding: false,
    explosionProgress: 0,
    attractedToMouse: false,
    gravitySources: [],
    attractingParticles: []
  };
  
  particlesRef.current.push(newParticle);
  return newParticle;
};

// 计算当前总粒子数
export const getTotalParticleCount = (
  particlesRef: React.MutableRefObject<Particle[]>
): number => {
  return particlesRef.current.length;
};

// 删除一个随机粒子
export const removeRandomParticle = (
  particlesRef: React.MutableRefObject<Particle[]>
): void => {
  // 找出可以被移除的粒子(不是正在爆炸或合并的粒子)
  const removableParts = particlesRef.current.filter(p => !p.merging && !p.exploding);
  if (removableParts.length === 0) return; // 没有可以移除的粒子
  
  // 随机选择一个粒子移除
  const removeIndex = Math.floor(Math.random() * removableParts.length);
  const particleToRemove = removableParts[removeIndex];
  const indexInMain = particlesRef.current.findIndex(p => p.id === particleToRemove.id);
  
  if (indexInMain !== -1) {
    particlesRef.current.splice(indexInMain, 1);
  }
};

// 触发大爆炸效果
export const triggerBigBang = (
  particle: Particle,
  canvas: HTMLCanvasElement,
  particlesRef: React.MutableRefObject<Particle[]>
): void => {
  // 标记为爆炸状态
  particle.exploding = true;
  particle.explosionProgress = 0;
  particle.explosionParticles = [];
  
  // 确定爆炸将产生的粒子数量(基于原粒子的合并数量)
  const particleCount = Math.min(particle.mergeCount || 1, BIG_BANG_PARTICLE_COUNT);
  
  // 保存原始颜色，为生成新粒子使用
  const originalColor = particle.color;
  
  // 生成爆炸碎片
  const fragmentCount = particleCount;
  for (let i = 0; i < fragmentCount; i++) {
    const angle = Math.random() * Math.PI * 2;
    // 减小速度和大小的变化范围，使效果更自然
    const speed = 1 + Math.random() * 4;  // 减小速度
    const size = 1.5 + Math.random() * 3;  // 减小碎片尺寸
    
    particle.explosionParticles!.push({
      x: 0, // 相对坐标
      y: 0,
      speedX: Math.cos(angle) * speed,
      speedY: Math.sin(angle) * speed,
      size: size,
      opacity: 0.8 + Math.random() * 0.2  // 保持较高不透明度
    });
  }
  
  // 在爆炸位置添加新的小粒子 - 爆炸结束后会创建
  setTimeout(() => {
    // 如果组件已经卸载，不进行任何操作
    if (!particlesRef.current) return;
    
    // 在能量守恒模式下，根据合并数量创建新粒子
    if (ENERGY_CONSERVATION) {
      // 创建新的颜色
      const newColors = [
        'rgba(255, 120, 70, 0.8)',  // 橙红色
        'rgba(255, 190, 60, 0.8)',  // 金黄色 
        'rgba(150, 200, 255, 0.8)', // 淡蓝色
        'rgba(180, 130, 255, 0.8)'  // 淡紫色
      ];
      
      // 检查当前总粒子数，确保不超过MAX_PARTICLES
      const currentCount = getTotalParticleCount(particlesRef);
      let availableSlots = MAX_PARTICLES - currentCount;
      
      // 如果没有可用槽位但需要创建新粒子，则移除一些随机粒子
      if (availableSlots <= 0 && particleCount > 0) {
        // 移除几个粒子，为新粒子腾出空间
        const particlesToRemove = Math.min(particleCount, 5); // 最多移除5个
        for (let i = 0; i < particlesToRemove; i++) {
          removeRandomParticle(particlesRef);
        }
        availableSlots = MAX_PARTICLES - getTotalParticleCount(particlesRef);
       }
      
      // 创建新粒子，数量不超过可用槽位
      const createCount = Math.min(particleCount, availableSlots);
      for (let i = 0; i < createCount; i++) {
        const angle = Math.random() * Math.PI * 2;
        const distance = 40 + Math.random() * BIG_BANG_MAX_DISTANCE;
        const newX = particle.x + Math.cos(angle) * distance;
        const newY = particle.y + Math.sin(angle) * distance;
        
        // 随机选择一个新颜色
        const newColor = newColors[Math.floor(Math.random() * newColors.length)];
        
        // 新粒子的大小设置较小
        createParticle(
          canvas,
          particlesRef,
          newX,
          newY,
          PARTICLE_SIZE_RANGE.min + Math.random() * 2,
          (Math.random() - 0.5) * 1.5,
          (Math.random() - 0.5) * 1.5,
          newColor
        );
      }
    } else {
      // 非能量守恒模式
      for (let i = 0; i < BIG_BANG_PARTICLE_COUNT; i++) {
        const angle = Math.random() * Math.PI * 2;
        const distance = 40 + Math.random() * BIG_BANG_MAX_DISTANCE;
        const newX = particle.x + Math.cos(angle) * distance;
        const newY = particle.y + Math.sin(angle) * distance;
        
        createParticle(
          canvas,
          particlesRef,
          newX,
          newY,
          PARTICLE_SIZE_RANGE.min + Math.random() * 2.5,
          (Math.random() - 0.5) * 1.5,
          (Math.random() - 0.5) * 1.5
        );
      }
    }
  }, 200);
};

// 检查点是否在登录表单区域内
export const isPointInFormArea = (
  x: number, 
  y: number, 
  canvas: HTMLCanvasElement,
  formPositionRef: React.MutableRefObject<{x: number, y: number, width: number, height: number}>
): boolean => {
  const formPos = formPositionRef.current;
  
  const formLeft = canvas.width * (formPos.x - formPos.width/2);
  const formRight = canvas.width * (formPos.x + formPos.width/2);
  const formTop = canvas.height * (formPos.y - formPos.height/2);
  const formBottom = canvas.height * (formPos.y + formPos.height/2);
  
  return x > formLeft && x < formRight && y > formTop && y < formBottom;
}; 